﻿#include "ssThreadCondition.h"
#include "../../ssAssert.h"
#include <time.h>

namespace StarSeeker
{

ssThreadCondition::ssThreadCondition(void)
{
#ifdef SS_USE_BOOST_THREAD

#elif defined _WIN32
	InitializeConditionVariable(&m_cond);
#else
	SS_ASSERT(pthread_cond_init(&m_cond, 0)==0);
#endif
	m_pLock = 0;
}

ssThreadCondition::ssThreadCondition(ssThreadLock* lk)
{
#ifdef SS_USE_BOOST_THREAD

#elif defined _WIN32
	InitializeConditionVariable(&m_cond);
#else
	SS_ASSERT(pthread_cond_init(&m_cond, 0)==0);
#endif
	m_pLock = lk;
}

ssThreadCondition::~ssThreadCondition(void)
{
#ifdef SS_USE_BOOST_THREAD

#elif defined _WIN32

#else
	SS_ASSERT(pthread_cond_destroy(&m_cond)==0);
#endif
}

void ssThreadCondition::BindLock(ssThreadLock* lk)
{
	m_pLock = lk;
}

void ssThreadCondition::Wait()
{
	if (m_pLock)
	{
#ifdef SS_USE_BOOST_THREAD
		m_cond.wait(m_pLock->m_mutex);
#elif defined _WIN32
		SleepConditionVariableCS(&m_cond, &m_pLock->m_mutex, INFINITE);
#else
		pthread_cond_wait(&m_cond, &m_pLock->m_mutex);
#endif
	}
}

void ssThreadCondition::WaitTime(unsigned int msec)
{
	if (m_pLock)
	{
#ifdef SS_USE_BOOST_THREAD
		m_cond.timed_wait(m_pLock->m_mutex, boost::posix_time::milliseconds(msec));
#elif defined _WIN32
		SleepConditionVariableCS(&m_cond, &m_pLock->m_mutex, msec);
#else
		timespec abst;
		abst.tv_sec = time(0) + msec/1000;
		abst.tv_nsec = (msec%1000)*1000000;
		pthread_cond_timedwait(&m_cond, &m_pLock->m_mutex, &abst);
#endif
	}
}

void ssThreadCondition::NotifyOne()
{
	if (m_pLock)
	{
#ifdef SS_USE_BOOST_THREAD
		m_cond.notify_one();
#elif defined _WIN32
		WakeConditionVariable(&m_cond);
#else
		pthread_cond_signal(&m_cond);
#endif
	}
}

void ssThreadCondition::NotifyAll()
{
	if (m_pLock)
	{
#ifdef SS_USE_BOOST_THREAD
		m_cond.notify_all();
#elif defined _WIN32
		WakeAllConditionVariable(&m_cond);
#else
		pthread_cond_broadcast(&m_cond);
#endif
	}
}

}
